From 63126131de72d0c5133666fe8703d062463bf0e9 Mon Sep 17 00:00:00 2001 From: "cl349@arcadians.cl.cam.ac.uk" Date: Fri, 19 Nov 2004 15:37:35 +0000 Subject: [PATCH] bitkeeper revision 1.1159.179.12 (419e133foVH755X0bQ79WRObEybang) Add teardown_irq and update do_IRQ interface to match the Linux 2.6 one. --- .rootkeys | 1 + linux-2.4.27-xen-sparse/arch/xen/kernel/irq.c | 78 ++++++++++++------ linux-2.4.27-xen-sparse/include/linux/irq.h | 80 +++++++++++++++++++ .../arch/xen/kernel/evtchn.c | 4 + 4 files changed, 138 insertions(+), 25 deletions(-) create mode 100644 linux-2.4.27-xen-sparse/include/linux/irq.h diff --git a/.rootkeys b/.rootkeys index 4152ff07fe..044186df4f 100644 --- a/.rootkeys +++ b/.rootkeys @@ -112,6 +112,7 @@ 3f1056a9L_kqHcFheV00KbKBzv9j5w linux-2.4.27-xen-sparse/include/asm-xen/vga.h 40659defgWA92arexpMGn8X3QMDj3w linux-2.4.27-xen-sparse/include/asm-xen/xor.h 3f056927gMHl7mWB89rb73JahbhQIA linux-2.4.27-xen-sparse/include/linux/blk.h +419e0488SBzS3mdUhwgsES5a5e3abA linux-2.4.27-xen-sparse/include/linux/irq.h 4124f66fPHG6yvB_vXmesjvzrJ3yMg linux-2.4.27-xen-sparse/include/linux/mm.h 401c0590D_kwJDU59X8NyvqSv_Cl2A linux-2.4.27-xen-sparse/include/linux/sched.h 40a248afgI0_JKthdYAe8beVfXSTpQ linux-2.4.27-xen-sparse/include/linux/skbuff.h diff --git a/linux-2.4.27-xen-sparse/arch/xen/kernel/irq.c b/linux-2.4.27-xen-sparse/arch/xen/kernel/irq.c index 8154c5b7c3..457ca3f553 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/kernel/irq.c +++ b/linux-2.4.27-xen-sparse/arch/xen/kernel/irq.c @@ -559,7 +559,7 @@ void enable_irq(unsigned int irq) * SMP cross-CPU interrupts have their own specific * handlers). */ -asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) +asmlinkage unsigned int do_IRQ(struct pt_regs *regs) { /* * We ack quickly, we don't want the irq controller @@ -571,6 +571,7 @@ asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ + int irq = regs->orig_eax & 0xff; /* high bits used in ret_from_ code */ int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; struct irqaction * action; @@ -731,32 +732,18 @@ int request_irq(unsigned int irq, return retval; } -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. The function - * does not return until any executing interrupts for this IRQ - * have completed. - * - * This function may be called from interrupt context. - * - * Bugs: Attempting to free an irq in a handler for the same irq hangs - * the machine. +/* + * Internal function to unregister an irqaction - typically used to + * deallocate special interrupts that are part of the architecture. */ - -void free_irq(unsigned int irq, void *dev_id) +int teardown_irq(unsigned int irq, struct irqaction * old) { irq_desc_t *desc; struct irqaction **p; unsigned long flags; if (irq >= NR_IRQS) - return; + return -ENOENT; desc = irq_desc + irq; spin_lock_irqsave(&desc->lock,flags); @@ -766,7 +753,7 @@ void free_irq(unsigned int irq, void *dev_id) if (action) { struct irqaction **pp = p; p = &action->next; - if (action->dev_id != dev_id) + if (action != old) continue; /* Found it - now remove it from the list of entries */ @@ -784,15 +771,56 @@ void free_irq(unsigned int irq, void *dev_id) cpu_relax(); } #endif -#define SA_STATIC_ACTION 0x01000000 /* Is it our duty to free the action? */ - if (!(action->flags & SA_STATIC_ACTION)) - kfree(action); - return; + return 0; } printk("Trying to free free IRQ%d\n",irq); spin_unlock_irqrestore(&desc->lock,flags); + return -ENOENT; + } +} + +/** + * free_irq - free an interrupt + * @irq: Interrupt line to free + * @dev_id: Device identity to free + * + * Remove an interrupt handler. The handler is removed and if the + * interrupt line is no longer in use by any driver it is disabled. + * On a shared IRQ the caller must ensure the interrupt is disabled + * on the card it drives before calling this function. The function + * does not return until any executing interrupts for this IRQ + * have completed. + * + * This function may be called from interrupt context. + * + * Bugs: Attempting to free an irq in a handler for the same irq hangs + * the machine. + */ + +void free_irq(unsigned int irq, void *dev_id) +{ + irq_desc_t *desc; + struct irqaction *action; + unsigned long flags; + + if (irq >= NR_IRQS) + return; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + for (action = desc->action; action != NULL; action = action->next) { + if (action->dev_id != dev_id) + continue; + + spin_unlock_irqrestore(&desc->lock,flags); + + if (teardown_irq(irq, action) == 0) + kfree(action); return; } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + return; } /* diff --git a/linux-2.4.27-xen-sparse/include/linux/irq.h b/linux-2.4.27-xen-sparse/include/linux/irq.h new file mode 100644 index 0000000000..7052672c2b --- /dev/null +++ b/linux-2.4.27-xen-sparse/include/linux/irq.h @@ -0,0 +1,80 @@ +#ifndef __irq_h +#define __irq_h + +/* + * Please do not include this file in generic code. There is currently + * no requirement for any architecture to implement anything held + * within this file. + * + * Thanks. --rmk + */ + +#include + +#if !defined(CONFIG_ARCH_S390) + +#include +#include + +#include +#include + +/* + * IRQ line status. + */ +#define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */ +#define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */ +#define IRQ_PENDING 4 /* IRQ pending - replay on enable */ +#define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */ +#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */ +#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */ +#define IRQ_LEVEL 64 /* IRQ level triggered */ +#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */ +#define IRQ_PER_CPU 256 /* IRQ is per CPU */ + +/* + * Interrupt controller descriptor. This is all we need + * to describe about the low-level hardware. + */ +struct hw_interrupt_type { + const char * typename; + unsigned int (*startup)(unsigned int irq); + void (*shutdown)(unsigned int irq); + void (*enable)(unsigned int irq); + void (*disable)(unsigned int irq); + void (*ack)(unsigned int irq); + void (*end)(unsigned int irq); + void (*set_affinity)(unsigned int irq, unsigned long mask); +}; + +typedef struct hw_interrupt_type hw_irq_controller; + +/* + * This is the "IRQ descriptor", which contains various information + * about the irq, including what kind of hardware handling it has, + * whether it is disabled etc etc. + * + * Pad this out to 32 bytes for cache and indexing reasons. + */ +typedef struct { + unsigned int status; /* IRQ status */ + hw_irq_controller *handler; + struct irqaction *action; /* IRQ action list */ + unsigned int depth; /* nested irq disables */ + spinlock_t lock; +} ____cacheline_aligned irq_desc_t; + +extern irq_desc_t irq_desc [NR_IRQS]; + +#include /* the arch dependent stuff */ + +extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); +extern int setup_irq(unsigned int , struct irqaction * ); +extern int teardown_irq(unsigned int , struct irqaction * ); + +extern hw_irq_controller no_irq_type; /* needed in every arch ? */ +extern void no_action(int cpl, void *dev_id, struct pt_regs *regs); + +#endif + +#endif /* __irq_h */ diff --git a/linux-2.6.10-rc2-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6.10-rc2-xen-sparse/arch/xen/kernel/evtchn.c index ba58bdd973..e5aa5a1b18 100644 --- a/linux-2.6.10-rc2-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6.10-rc2-xen-sparse/arch/xen/kernel/evtchn.c @@ -69,7 +69,11 @@ static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)]; /* Upcall to generic IRQ layer. */ #ifdef CONFIG_X86 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) extern fastcall unsigned int do_IRQ(struct pt_regs *regs); +#else +extern asmlinkage unsigned int do_IRQ(struct pt_regs *regs); +#endif #define do_IRQ(irq, regs) do { \ (regs)->orig_eax = (irq); \ do_IRQ((regs)); \ -- 2.30.2